package cn.iocoder.yudao.module.product.spu.controller.app;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.business.evaluation.enums.ScoreLevelEnum;
import cn.iocoder.yudao.framework.common.biz.dict.dto.DictDataRespDTO;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.api.dine.DineConfigApi;
import cn.iocoder.yudao.module.api.dine.enums.DineAttributeEnum;
import cn.iocoder.yudao.module.api.dine.vo.DineConfigVO;
import cn.iocoder.yudao.module.api.infrastructure.dict.DictDataApi;
import cn.iocoder.yudao.module.api.product.spu.enums.ProductPriceModeEnum;
import cn.iocoder.yudao.module.api.product.spu.enums.ProductSpuRecommendEnum;
import cn.iocoder.yudao.module.api.promotion.activity.enums.PromotionProductScopeEnum;
import cn.iocoder.yudao.module.api.promotion.coupon.CouponTemplateApi;
import cn.iocoder.yudao.module.api.promotion.coupon.dto.CouponTemplateRespDTO;
import cn.iocoder.yudao.module.api.shop.info.ShopInfoApi;
import cn.iocoder.yudao.module.api.trade.delivery.enums.DeliveryTypeEnum;
import cn.iocoder.yudao.module.product.evaluation.dal.dataobject.ProductEvaluationDO;
import cn.iocoder.yudao.module.product.evaluation.service.ProductEvaluationService;
import cn.iocoder.yudao.module.product.evaluation.vo.AppProductEvaluationLatestRespVO;
import cn.iocoder.yudao.module.product.favorite.service.AppProductFavoriteService;
import cn.iocoder.yudao.module.product.sku.vo.AppProductSkuRespVO;
import cn.iocoder.yudao.module.product.sku.vo.AppProductSkuSaveReqVO;
import cn.iocoder.yudao.module.product.spu.convert.ProductSpuConvert;
import cn.iocoder.yudao.module.product.spu.service.ProductSpuService;
import cn.iocoder.yudao.module.product.spu.vo.*;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.annotation.security.PermitAll;
import jakarta.validation.Valid;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.*;
import java.util.stream.Collectors;

import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.FORBIDDEN;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.error;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserLastShopId;
import static cn.iocoder.yudao.module.api.product.DictTypeConstants.PRODUCT_SPU_UNIT;

@Slf4j
@Tag(name = "用户 APP - 产品")
@RestController
@RequestMapping("/product/spu")
@Validated
public class AppProductSpuController {

    @Resource
    private ProductSpuService productSpuService;
    @Resource
    private AppProductFavoriteService productFavoriteService;
    @Resource
    private ProductEvaluationService productEvaluationService;

    @Resource
    private DictDataApi dictDataApi;
    @Resource
    private ShopInfoApi shopInfoApi;
    @Resource
    private CouponTemplateApi couponTemplateApi;
    @Resource
    private DineConfigApi dineConfigApi;

    @GetMapping("/page")
    @Operation(summary = "获得产品分页")
    @PermitAll
    public CommonResult<PageResult<AppProductSpuRespVO>> getSpuPage(@Valid AppProductSpuPageReqVO pageVO) {
        PageResult<AppProductSpuRespVO> pageResult = productSpuService.getSpuPage(pageVO);
        return toPageCommonResult(pageResult);
    }

    @GetMapping("/page-for-seller")
    @Operation(summary = "获得产品分页（商家）")
    @PreAuthorize("@mm.isMerchant()")
    public CommonResult<PageResult<AppProductSpuRespVO>> getSpuPageForSeller(@Valid AppProductSpuPageForSellerReqVO pageVO) {
        AppProductSpuPageReqVO vo = BeanUtils.toBean(pageVO, AppProductSpuPageReqVO.class);
        vo.setShopId(getLoginUserLastShopId());
        vo.setSortField("CREATE_TIME");
        vo.setSortAsc(false);
        PageResult<AppProductSpuRespVO> pageResult = productSpuService.getSpuPage(vo);
        return toPageCommonResult(pageResult);
    }

    @GetMapping("/page-by-platform-category")
    @Operation(summary = "获得产品分页 - 按行业类目来")
    @PermitAll
    public CommonResult<PageResult<AppProductSpuRespVO>> getSpuPageForPlatformCategory(@Valid AppProductSpuPageForPlatformCategoryReqVO pageVO) {
        PageResult<AppProductSpuRespVO> pageResult = productSpuService.getSpuPageByPlatformCategoryId(pageVO);
        return toPageCommonResult(pageResult);
    }

    @GetMapping("/page-by-product-category")
    @Operation(summary = "获得产品分页 - 按产品分类来")
    @PermitAll
    public CommonResult<PageResult<AppProductSpuRespVO>> getSpuPageForShopCategory(@Valid AppProductSpuPageForProductCategoryReqVO pageVO) {
        PageResult<AppProductSpuRespVO> pageResult = productSpuService.getSpuPageByProductCategoryId(pageVO);
        return toPageCommonResult(pageResult);
    }

    @GetMapping("/page-by-cloud-alliance")
    @Operation(summary = "获得产品分页 - 按云盟商城来")
    @PermitAll
    public CommonResult<PageResult<AppProductSpuRespVO>> getSpuPageForCloudAlliance(@Valid AppProductSpuPageForCloudAllianceReqVO pageVO) {
        PageResult<AppProductSpuRespVO> pageResult = productSpuService.getSpuPageByCloudAlliance(pageVO);
        return toPageCommonResult(pageResult);
    }

    @GetMapping("/page-by-dish-attribute")
    @Operation(summary = "获得产品分页 - 按菜品属性来")
    @PermitAll
    public CommonResult<PageResult<AppProductSpuRespVO>> getSpuPageForDishAttribute(@Valid AppProductSpuPageForDishAttributeReqVO pageVO) {
        PageResult<AppProductSpuRespVO> pageResult = productSpuService.getSpuPageByDishAttribute(pageVO);
        return toPageCommonResult(pageResult);
    }


    private CommonResult<PageResult<AppProductSpuRespVO>> toPageCommonResult(PageResult<AppProductSpuRespVO> pageResult) {
        List<AppProductSpuRespVO> list = pageResult.getList();
        if (CollUtil.isEmpty(list)) {
            return success(PageResult.empty(pageResult.getTotal()));
        }
        Set<Long> shopIds = list.stream().map(AppProductSpuRespVO::getShopId).collect(Collectors.toSet());
        Set<Long> spuIds = list.stream().map(AppProductSpuRespVO::getId).collect(Collectors.toSet());
        Map<Long, Boolean> favorites = productFavoriteService.getStateMap(spuIds, getLoginUserId());
        Map<Long, Float> scores = productEvaluationService.batchCalculateScoreBySpuIds(spuIds);
        Map<Long, List<CouponTemplateRespDTO>> couponTemplateMap = couponTemplateApi.getCanTakeCouponTemplateMap(shopIds);
        Map<Long, DineConfigVO> dineConfigs = dineConfigApi.getDetailMap(shopIds);
        for (AppProductSpuRespVO vo : list) {// 处理收藏状态
            vo.setFavorite(favorites.getOrDefault(vo.getId(), false));
            // 处理销量 TODO 月销量从已付款订单计算得来
            vo.setSalesCountPerMonth(NumberUtil.nullToZero(vo.getSalesCount()));
            // 处理评分
            vo.setScore(scores.getOrDefault(vo.getId(), 5.0F));
            vo.setScoreLevel(ScoreLevelEnum.fromScore(vo.getScore()).getValue());
            // 处理优惠券
            checkSpuHasCoupon(vo, couponTemplateMap.getOrDefault(vo.getShopId(), Collections.emptyList()));
            // 适配 UNIAPP 的 SKU 组件
            vo.setUniapp(ProductSpuConvert.INSTANCE.convert2(vo));
            // 适配称重计价模式
            if (Objects.equals(vo.getPriceMode(), ProductPriceModeEnum.TOTAL_WEIGHT.getValue())) {
                DineConfigVO dineConfigVO = dineConfigs.get(vo.getShopId());
                if (dineConfigVO != null) {
                    vo.setUnitName(dineConfigVO.getWeightUnitName());
                    int unitPrice = dineConfigVO.getVegetableUnitPrice();
                    if (Objects.equals(vo.getDishAttribute(), DineAttributeEnum.MEAT.getValue())) {
                        unitPrice = dineConfigVO.getMeatUnitPrice();
                    }
                    vo.setPrice(vo.getStepQuantity() * unitPrice);
                    vo.setVipPrice(vo.getPrice());
                    vo.setCostPrice(0);
                    for (AppProductSkuRespVO it : vo.getSkus()) {
                        it.setPrice(it.getPrice() * vo.getStepQuantity());
                        it.setVipPrice(it.getPrice());
                        it.setCostPrice(0);
                    }
                }
            }
        }
        return success(pageResult);
    }

    private void checkSpuHasCoupon(AppProductSpuRespVO respVO, List<CouponTemplateRespDTO> couponTemplates) {
        respVO.setHasCoupon(false);
        if (CollUtil.isEmpty(couponTemplates)) {
            return;
        }
        for (CouponTemplateRespDTO couponTemplate : couponTemplates) {
            if (Objects.equals(couponTemplate.getProductScope(), PromotionProductScopeEnum.ALL.getScope())) {
                respVO.setHasCoupon(true);
                break;
            } else if (Objects.equals(couponTemplate.getProductScope(), PromotionProductScopeEnum.SPU.getScope())
                       && CollUtil.contains(couponTemplate.getProductScopeValues(), respVO.getId())) {
                respVO.setHasCoupon(true);
                break;
            } else if (Objects.equals(couponTemplate.getProductScope(), PromotionProductScopeEnum.CATEGORY.getScope())
                       && CollUtil.contains(couponTemplate.getProductScopeValues(), respVO.getCategoryId())) {
                respVO.setHasCoupon(true);
                break;
            }
        }
    }

    @GetMapping("/get-detail")
    @Operation(summary = "获得产品明细")
    @Parameter(name = "id", description = "编号", required = true)
    @PermitAll
    public CommonResult<AppProductSpuDetailRespVO> getSpuDetail(@RequestParam("id") Long id) {
        AppProductSpuDetailRespVO vo = productSpuService.browseSpu(getLoginUserId(), id);
        // 处理店铺信息
        vo.setShop(shopInfoApi.getShopInfo(vo.getShopId()));
        // 处理销量 TODO 月销量从已付款订单计算得来
        vo.setSalesCountPerMonth(NumberUtil.nullToZero(vo.getSalesCount()));
        // 处理收藏状态
        vo.setFavorite(productFavoriteService.isTrue(vo.getId(), getLoginUserId()));
        // 处理评分
        vo.setScore(productEvaluationService.calculateScoreBySpuId(vo.getId()));
        vo.setScoreLevel(ScoreLevelEnum.fromScore(vo.getScore()).getValue());
        // 处理优惠券
        List<CouponTemplateRespDTO> couponTemplates = couponTemplateApi.getCanTakeCouponTemplateListByShopId(vo.getShopId());
        checkSpuHasCoupon(vo, couponTemplates);
        // 处理评论
        ProductEvaluationDO commentDO = productEvaluationService.getLatestCommentBySpuId(vo.getId());
        vo.setLatestComment(BeanUtils.toBean(commentDO, AppProductEvaluationLatestRespVO.class));
        // 适配 UNIAPP 的 SKU 组件
        vo.setUniapp(ProductSpuConvert.INSTANCE.convert2(vo));
        // 适配称重计价模式
        if (Objects.equals(vo.getPriceMode(), ProductPriceModeEnum.TOTAL_WEIGHT.getValue())) {
            DineConfigVO dineConfigVO = dineConfigApi.getDetail(vo.getShopId());
            if (dineConfigVO != null) {
                vo.setUnitName(dineConfigVO.getWeightUnitName());
                int unitPrice = dineConfigVO.getVegetableUnitPrice();
                if (Objects.equals(vo.getDishAttribute(), DineAttributeEnum.MEAT.getValue())) {
                    unitPrice = dineConfigVO.getMeatUnitPrice();
                }
                vo.setPrice(vo.getStepQuantity() * unitPrice);
                vo.setVipPrice(vo.getPrice());
                vo.setCostPrice(0);
                for (AppProductSkuRespVO it : vo.getSkus()) {
                    it.setPrice(it.getPrice() * vo.getStepQuantity());
                    it.setVipPrice(it.getPrice());
                    it.setCostPrice(0);
                }
            }
        }
        return success(vo);
    }

    @GetMapping("/get-detail-for-seller")
    @Operation(summary = "获得产品明细（商家）", description = "会返回成本价")
    @Parameter(name = "id", description = "编号", required = true)
    @PreAuthorize("@mm.isMerchant()")
    public CommonResult<AppShopProductSpuDetailRespVO> getSpuDetailForEdit(@RequestParam("id") Long id) {
        AppShopProductSpuDetailRespVO data = productSpuService.shopSpu(id);
        if (Objects.equals(getLoginUserLastShopId(), data.getShopId())) {
            return error(FORBIDDEN.getCode(), "没有该店铺的操作权限");
        }
        return success(data);
    }

    @GetMapping("/get-count")
    @Operation(summary = "获得产品页签统计", description = "用于产品列表页在页签上展示数量")
    @Parameter(name = "type", description = "类型：mall-商城、food-美食、hotel-酒店……", example = "mall")
    @PermitAll
    public CommonResult<Map<String, Long>> getSpuCount(@RequestParam(value = "type", required = false) String type) {
        return success(productSpuService.getSpuCount(null, type));
    }

    @GetMapping("/get-count-for-seller")
    @Operation(summary = "获得产品页签统计（商家）", description = "用于产品列表页在页签上展示数量")
    @Parameter(name = "type", description = "类型：mall-商城、food-美食、hotel-酒店……", example = "mall")
    @PreAuthorize("@mm.isMerchant()")
    public CommonResult<Map<String, Long>> getSpuCountForSeller(@RequestParam(value = "type", required = false) String type) {
        return success(productSpuService.getSpuCount(getLoginUserLastShopId(), type));
    }

    @GetMapping("/get-unit-list")
    @Operation(summary = "获得产品单位列表", description = "用于描述产品的单位，如：件、个、箱、套")
    @PermitAll
    public CommonResult<List<DictDataRespDTO>> getSpuUnitList() {
        return success(dictDataApi.getDictDataList(PRODUCT_SPU_UNIT));
    }

    @PostMapping("/create")
    @Operation(summary = "创建产品")
    @PreAuthorize("@mm.isMerchant()")
    public CommonResult<Long> createSpu(@Valid @RequestBody AppProductSpuSaveReqVO createReqVO) {
        return success(productSpuService.createSpu(createReqVO));
    }

    @PostMapping("/create-basic")
    @Operation(summary = "创建产品")
    @PreAuthorize("@mm.isStaff()")
    public CommonResult<Long> createSpuBasic(@Valid @RequestBody AppProductSpuBasicSaveVO createReqVO) {
        AppProductSpuSaveReqVO reqVO = BeanUtils.toBean(createReqVO, AppProductSpuSaveReqVO.class);
        reqVO.setPlatformCategoryId(1865335412799713282L); // TODO 暂时写死，后续再说
        reqVO.setSpecType(false);
        if (StrUtil.isBlank(createReqVO.getDescription())) {
            reqVO.setDescription("<p>暂无</p>");
        } else {
            reqVO.setDescription(createReqVO.getDescription());
        }
        reqVO.setDeliveryTypes(List.of(DeliveryTypeEnum.NONE.getType()));
        AppProductSkuSaveReqVO skuSaveReqVO = new AppProductSkuSaveReqVO();
        skuSaveReqVO.setName(createReqVO.getName());
        skuSaveReqVO.setPrice(createReqVO.getPrice());
        skuSaveReqVO.setVipPrice(createReqVO.getPrice());
        skuSaveReqVO.setCostPrice(0);
        skuSaveReqVO.setStock(createReqVO.getStock());
        skuSaveReqVO.setPicUrl(createReqVO.getPicUrl());
        reqVO.setSkus(List.of(skuSaveReqVO));
        return success(productSpuService.createSpu(reqVO));
    }

    @PostMapping("/update")
    @Operation(summary = "更新产品")
    @PreAuthorize("@mm.isMerchant()")
    public CommonResult<Boolean> updateSpu(@Valid @RequestBody AppProductSpuSaveReqVO updateReqVO) {
        productSpuService.updateSpu(updateReqVO);
        return success(true);
    }

    @PostMapping("/update-basic")
    @Operation(summary = "更新产品")
    @PreAuthorize("@mm.isStaff()")
    public CommonResult<Boolean> updateSpuBasic(@Valid @RequestBody AppProductSpuBasicSaveVO updateReqVO) {
        AppProductSpuSaveReqVO reqVO = BeanUtils.toBean(updateReqVO, AppProductSpuSaveReqVO.class);
        reqVO.setPlatformCategoryId(1865335412799713282L); // TODO 暂时写死，后续再说
        reqVO.setSpecType(false);
        if (reqVO.getSkus() == null) {
            reqVO.setSkus(List.of());
        }
        if (StrUtil.isBlank(updateReqVO.getDescription())) {
            reqVO.setDescription("<p>暂无</p>");
        } else {
            reqVO.setDescription(updateReqVO.getDescription());
        }
        for (AppProductSkuSaveReqVO it : reqVO.getSkus()) {
            it.setName(updateReqVO.getName());
            it.setPrice(updateReqVO.getPrice());
            it.setVipPrice(updateReqVO.getPrice());
            it.setCostPrice(0);
            it.setPicUrl(updateReqVO.getPicUrl());
            it.setStock(updateReqVO.getStock());
        }
        productSpuService.updateSpu(reqVO);
        return success(true);
    }

    @PostMapping("/update-status")
    @Operation(summary = "设置产品状态")
    @PreAuthorize("@mm.isMerchant()")
    public CommonResult<Boolean> updateStatus(@Valid @RequestBody AppProductSpuUpdateStatusReqVO updateReqVO) {
        productSpuService.updateSpuStatus(updateReqVO);
        return success(true);
    }

    @PostMapping("/update-recommend")
    @Operation(summary = "设置产品推荐类型")
    @PreAuthorize("@mm.isMerchant()")
    public CommonResult<Boolean> updateRecommend(@Valid @RequestBody AppProductSpuUpdateRecommendReqVO updateReqVO) {
        if (ProductSpuRecommendEnum.ADVERT.getValue().equals(updateReqVO.getRecommend())) {
            return error(FORBIDDEN.getCode(), "没有权限设置为" + ProductSpuRecommendEnum.ADVERT.getName());
        }
        productSpuService.updateSpuRecommend(updateReqVO);
        return success(true);
    }

    @PostMapping("/update-integral")
    @Operation(summary = "设置/取消为积分产品")
    @PreAuthorize("@mm.isMerchant()")
    public CommonResult<Boolean> updateIntegral(@Valid @RequestBody AppProductSpuUpdateIntegralReqVO updateReqVO) {
        productSpuService.updateSpuIntegral(updateReqVO);
        return success(true);
    }

    @GetMapping("/delete")
    @Operation(summary = "删除产品")
    @Parameter(name = "id", description = "编号", required = true, example = "1024")
    @PreAuthorize("@mm.isMerchant()")
    public CommonResult<Boolean> deleteSpu(@RequestParam("id") Long id) {
        productSpuService.deleteSpu(id);
        return success(true);
    }

}
